package com.jy.modules.cims.buyback.service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.sysUtils.DateTimeUtils;
import com.jy.modules.cims.data.common.dto.TCMmCooperorgDealDTO;
import com.jy.modules.cims.data.common.dto.TCMmCostParamDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditDealDetailDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditDetailDTO;
import com.jy.modules.cims.data.common.dto.TCMmRaisePlanDTO;
import com.jy.modules.cims.data.dto.CreditDetailDto;

/**
 * 回购信息保存
 */
@Service("com.jy.modules.cims.buyback.service.BuyBackSaveService")
public class BuyBackSaveService extends BuyBackCommonService {

	/**
	 * 保存流水、交易明细 、更新债权主档信息RedemptionStatus（赎回债权可选状态）
	 */
	public String insertLoanCreditDetail(String redemptionDate, String cooperorgCode, String agreementCode,
			String contractCode, String packageName, String userId, String[] deleteContractNoArr)
			throws Exception {
		//查询回购的贷款债权明细
		List<TCMmCreditDetailDTO> creditDetailList = getBuyBackDetail(cooperorgCode, contractCode, packageName, 
													redemptionDate, deleteContractNoArr);
		if (creditDetailList == null || creditDetailList.size() == 0) {
			throw new RuntimeException("包:" + packageName + ",回购日期:"+ redemptionDate+", 没有贷款可以回购");
		}
		
		//校验募集计划费用
		Map<String, Object> checkMap = new HashMap<String, Object>();
		checkPlanFee(creditDetailList, checkMap);
		String planId = (String) checkMap.get("planId");
		Long merchantPeriod = (Long) checkMap.get("merchantPeriod");
		BigDecimal interest = (BigDecimal) checkMap.get("interest");
		
		// 生成流水号
		StringBuffer dealCodesb = new StringBuffer();
		creditRedemptionService.doGetDealCode(dealCodesb);
		String dealCode = dealCodesb.toString();
		BigDecimal sumCreditorValue = BigDecimal.ZERO;
		BigDecimal sumTotalValue = BigDecimal.ZERO;
		BigDecimal sumMatchValue = BigDecimal.ZERO;
		TCMmCreditDetailDTO creditDetailDTO = null;
		Date redeemDate = DateTimeUtils.parseDate(redemptionDate, "yyyy-MM-dd");
		Timestamp currTime = new Timestamp(System.currentTimeMillis());
		//月还处理方式
		String repayType = getRepayType(contractCode);
		CreditDetailDto creditParam = null;
		for (int i = 0; i < creditDetailList.size(); i++) {
			creditDetailDTO = creditDetailList.get(i);
			// 债权交易明细DTO组装
			TCMmCreditDealDetailDTO creditDealDetailDTO = new TCMmCreditDealDetailDTO();
			String transferId = creditDetailDTO.getTransferId();
			creditDealDetailDTO.setDealStreamCode(dealCode);// 交易流水号
			creditDealDetailDTO.setAgreementCode(creditDetailDTO.getAgreementCode());// 协议编号
			creditDealDetailDTO.setTransferId(transferId);// 债权转让编号
			creditDealDetailDTO.setCreditorId(creditDetailDTO.getCreditCode());// 债权编号
			creditDealDetailDTO.setCooperorgCode(creditDetailDTO.getCooperorgCode());// 转让合作机构编号
			creditDealDetailDTO.setCreditorStatus(creditDetailDTO.getCreditorStatus());// 债权状态
			creditDealDetailDTO.setCooperativeAgencyProType(creditDetailDTO.getCooperativeAgencyProType());// 合作机构产品类型
			creditDealDetailDTO.setDeliverDate(redeemDate);// 交割日期
			creditDealDetailDTO.setRedeemDate(redeemDate);// 回购日期
			creditDealDetailDTO.setThisMakeCreditorValue(creditDetailDTO.getThisMakeCreditorValue());// 本次转让债权价值
			creditDealDetailDTO.setThisRepaySum(creditDetailDTO.getThisRepaySum());// 本期还款金额
			creditDealDetailDTO.setRepayPeriod(creditDetailDTO.getRepayPeriod());// 还款期数
			creditDealDetailDTO.setResidueRepayPeriod(creditDetailDTO.getResidueRepayPeriod());// 剩余还款期数
			creditDealDetailDTO.setThisCreditorValue(creditDetailDTO.getThisCreditorValue());// 当前债权价值
			creditDealDetailDTO.setCautionMoney(creditDetailDTO.getCautionMoney());//保证金
			creditDealDetailDTO.setCreateTime(currTime);// 创建时间
			creditDealDetailDTO.setModifyTime(currTime);
			creditDealDetailDTO.setCreateBy(userId);
			creditDealDetailDTO.setCostState(CimsConstant.COST_STATUS_WJ);
			
			//回购贷款价格
			BigDecimal makeCreditorValue = getBackContractValue(creditDetailDTO);
			creditDealDetailDTO.setMakeCreditorValue(makeCreditorValue);//回购价格
			
			//回购到期日本息和=合同金额+(合同金额*年利率/365*期限）
			BigDecimal backTotalValue = getBackTotalAmt(merchantPeriod, interest, creditDetailDTO, repayType);
			creditDealDetailDTO.setBackTotalValue(backTotalValue);//回购到期日本息和
			
			//回购匹债权金额=本息和-回购价格-已返现
			creditParam = getMatchParam(creditDetailDTO, makeCreditorValue, redeemDate,
					transferId, backTotalValue);
			BigDecimal backMatchValue = getMatchAmt(creditParam, contractCode, repayType);
			creditDealDetailDTO.setBackMatchValue(backMatchValue);//回购匹债权金额
			
			//保存关系表
			creditDealDetailService.insertTCMmCreditDealDetail(creditDealDetailDTO);
			
			//更新债权明细表
			Map<String, Object> updateMap = new HashMap<String, Object>();
			updateMap.put("id", creditDetailDTO.getId());
			updateMap.put("chooseStatus", CimsConstant.CREDIT_REDEMPTION_UNCK);//02-已经选择
			updateMap.put("redeemDate", redeemDate);
			buyBackDao.updateCreditChooseStatus(updateMap);
			
			// 汇总回购价格
			sumCreditorValue = sumCreditorValue.add(creditDealDetailDTO.getMakeCreditorValue());
			// 汇总本息和
			sumTotalValue = sumTotalValue.add(backTotalValue);
			// 汇总匹债权金额
			sumMatchValue = sumMatchValue.add(backMatchValue);
		}

		// 交易流水DTO组装
		TCMmCooperorgDealDTO cooperorgDealDTO = new TCMmCooperorgDealDTO();
		cooperorgDealDTO.setDealCode(dealCode);// 交易流水号
		cooperorgDealDTO.setCooperorgCode(cooperorgCode);// 合作机构
		cooperorgDealDTO.setDealDate(new Date());// 交易日期
		cooperorgDealDTO.setDealType(CimsConstant.DEAL_TYPE_LOAN_CREDIT_REDEEM);// 交易类型
		cooperorgDealDTO.setAgreementCode(agreementCode);// 协议编号
		cooperorgDealDTO.setContractCode(contractCode);// 合约编号
		cooperorgDealDTO.setCooperativeAgencyDealStatus(CimsConstant.DEAL_STATUS_CREATE);// 合作机构交易状态
		cooperorgDealDTO.setDetialNumber(creditDetailList.size());// 明细数目
		cooperorgDealDTO.setSumCreditorValue(sumCreditorValue);// 汇总债权价值
		cooperorgDealDTO.setPlanSellSum(sumTotalValue);//汇总本息和
		cooperorgDealDTO.setPracticalSellSum(sumMatchValue);//汇总匹债权金额
		cooperorgDealDTO.setCreateTime(currTime);// 创建时间
		cooperorgDealDTO.setBillDate(creditDetailList.get(0).getBillDate());// 账单日
		cooperorgDealDTO.setCreditPackageName(packageName);// 债权包名
		cooperorgDealDTO.setRedemptionDate(redeemDate);// 回购日期
		cooperorgDealDTO.setModifyTime(currTime);// 修改时间
		cooperorgDealDTO.setPlanId(planId);
		cooperorgDealService.insertTCMmCooperorgDeal(cooperorgDealDTO);

		return dealCode;
	}


	/**
	 * 回购贷款价格
	 * @param creditDetailDTO
	 * @return
	 */
	private BigDecimal getBackContractValue(TCMmCreditDetailDTO creditDetailDTO) {
		BigDecimal makeCreditorValue = null;
		if (CimsConstant.CREDIT_STATUS_END.equals(creditDetailDTO.getCreditorStatus())) {
			//债权状态为泯灭：回购债权价值=0
			makeCreditorValue = BigDecimal.ZERO;
		} else if (!CimsConstant.CORE_CREDIT_STATUS_TRANSFER.equals(creditDetailDTO.getCoreCreditStatus())) {
			//核心债权状态为提前结清：回购债权价值=当前价值
			makeCreditorValue = creditDetailDTO.getThisCreditorValue();
		} else {
			//核心债权状态为01正常： 回购债权价值=回购日债权价值
			makeCreditorValue = creditDetailDTO.getThisMakeCreditorValue();
		}
		return makeCreditorValue;
	}
	
	
	/**
	 * 得到回购到期日本息和
	 * @param merchantPeriod
	 * @param interest
	 * @param creditDetailDTO
	 * @return
	 */
	private BigDecimal getBackTotalAmt(Long merchantPeriod,
			BigDecimal interest, TCMmCreditDetailDTO creditDetailDTO, String repayType) {
		BigDecimal contractAmt = creditDetailDTO.getContractSum();
		BigDecimal backTotalValue = null;
		if (CimsConstant.REPLACE_TYPE_FULL_MATCH.equals(repayType) ) {
			//全匹债权
			//合同金额 + 合同金额*服务费率*期限/365
			backTotalValue = contractAmt.add( contractAmt.multiply(interest).multiply(BigDecimal.valueOf(merchantPeriod)).divide(BigDecimal.valueOf(365), 2, BigDecimal.ROUND_HALF_UP) );
		} else if (CimsConstant.REPLACE_TYPE_FULL_RETURN.equals(repayType) ) {
			//全匹现金
			backTotalValue = getBackContractValue(creditDetailDTO);
		} else {
			//本金匹债权利息返现
			//TODO 合同金额 + 合同金额*服务费率*期限/365
			backTotalValue = contractAmt.add( contractAmt.multiply(interest).multiply(BigDecimal.valueOf(merchantPeriod)).divide(BigDecimal.valueOf(365), 2, BigDecimal.ROUND_HALF_UP) );
		}
		return backTotalValue;
	}

	/**
	 * @param creditDetailDTO
	 * @param redeemDate
	 * @param transferId
	 * @param backTotalValue
	 * @return
	 */
	private CreditDetailDto getMatchParam(TCMmCreditDetailDTO creditDetailDTO,
			BigDecimal makeCreditorValue, Date redeemDate, String transferId, BigDecimal backTotalValue) {
		CreditDetailDto dto = new CreditDetailDto();
		dto.setTransferId(transferId);
		dto.setCreditorStatus(creditDetailDTO.getCreditorStatus());
		dto.setBizDate(creditDetailDTO.getBizDate());
		dto.setRedeemDate(redeemDate);
		dto.setMakeCreditorValue(makeCreditorValue);
		dto.setBackTotalValue(backTotalValue);
		return dto;
	}

	
	
	/**
	 * 得到募集计划ID
	 * @param creditDetailList
	 * @return
	 */
	private TCMmRaisePlanDTO getPlan(List<TCMmCreditDetailDTO> creditDetailList) {
		//根据合同号查询募集计划ID
		TCMmCreditDetailDTO creditDetailDTO = creditDetailList.get(0);
		String contractNo = creditDetailDTO.getCreditCode();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("contractNo", contractNo);
		List<TCMmRaisePlanDTO> planList = buyBackDao.getPlan(map);
		if (CollectionUtils.isEmpty(planList)) {
			throw new RuntimeException("贷款没有找到募集计划，合同号=" + contractNo);
		}
		TCMmRaisePlanDTO plan = planList.get(0);
		return plan;
	}
	
	/**
	 * 校验募集计划费用
	 * @param creditDetailList
	 * @return
	 */
	private void checkPlanFee(List<TCMmCreditDetailDTO> creditDetailList, Map<String, Object> checkMap) {
		//根据合同号查询募集计划
		TCMmRaisePlanDTO plan = getPlan(creditDetailList);
		String planId = plan.getPlanId();

		Long merchantPeriod = plan.getMerchantPeriod();
		if (merchantPeriod == null || merchantPeriod.longValue() == 0L) {
			throw new RuntimeException("募集计划["+ planId+"]没有配置商户兑付期限(天)");
		}
		
		//查询批次的募集计划对应的费用
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("planId", planId);
		List<TCMmCostParamDTO> feeList = buyBackDao.getFee(map);
		if (CollectionUtils.isEmpty(feeList)) {
			throw new RuntimeException("募集计划["+ planId+"]没有配置费用参数");
		}
	 
		//校验利率
		TCMmCostParamDTO fee = feeList.get(0);
		BigDecimal serviceFeeRatio = fee.getServiceFeeRatio();//服务费费率
		BigDecimal packageRatio = fee.getPackageRatio();//打包价
		if (serviceFeeRatio == null || serviceFeeRatio.compareTo(BigDecimal.ZERO) == 0) {
			throw new RuntimeException("募集计划["+ planId+"]没有配置服务费率");
		}
		if (packageRatio == null || packageRatio.compareTo(BigDecimal.ZERO) == 0) {
			throw new RuntimeException("募集计划["+ planId+"]没有配置打包价率");
		}
		if (packageRatio.compareTo(serviceFeeRatio) < 0) {
			throw new RuntimeException("募集计划["+ planId+"]打包价率不能小于服务费率");
		}
		//计算年利率
		BigDecimal interest = packageRatio.subtract(serviceFeeRatio);
		
		//存放结果
		checkMap.put("planId", planId);
		checkMap.put("merchantPeriod", merchantPeriod);
		checkMap.put("interest", interest);
	}

	
	/**
	 * 查询贷款回购贷款债权（ 不分页）
	 */
	private List<TCMmCreditDetailDTO> getBuyBackDetail(String cooperorgCode, String contractCode,
			String packageNum, String redemptionDate, String[] deleteContractNoArr) throws ParseException {
		List<TCMmCreditDetailDTO> list = new ArrayList<TCMmCreditDetailDTO>();
		//组装查询条件
		Map<String, Object> searchCreditParams = getBuyBackParamMap(
				contractCode, packageNum, redemptionDate);
		if (deleteContractNoArr != null && deleteContractNoArr.length > 0) {
			searchCreditParams.put("deleteContractNoArr", deleteContractNoArr);
		}
		//查询回购的贷款债权
		list = buyBackDao.searchBuyBackDetail(searchCreditParams);
		//得到赎回日债权价值
		if (list != null && list.size() > 0) {
			list = getBuyBackVal(list, redemptionDate);
		}
		return list;
	}
	
	
	
	

}
